/************************************************************************
This file is part of Polar4linux
Copyright (C) 2010-2011 Eric jrdn2
Portions Copyright (C) 2007 Matti Juvonen <mpj@iki.fi> (RS400 Tools)
Portions Copyright (C) 2006 Jani Hursti <jani.hursti@hut.fi>,
Portions Copyright (C) 2001-2003 Tom Oliveira e Silva

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
************************************************************************/

#include "RS400_file.h"

int checkFileExistence(const char filename[])
{
	struct stat stFileInfo; 
	return stat(filename,&stFileInfo);
}

std::string buildHRMfilename(const unsigned int year,const unsigned int month,const unsigned int day, const unsigned int exNum)
{
	char filename[100];
	sprintf(filename,"%2d%02d%02d%02d.hrm%c",year,month,day,exNum,'\0');
	return std::string(filename);
}

std::string buildPDDfilename(const unsigned int year,const unsigned int month,const unsigned int day)
{
	char filename[100];
	sprintf(filename,"%4d%02d%02d.pdd%c",year,month,day,'\0');
	return std::string(filename);
}

void saveBuffer(unsigned char *buf,unsigned int size,const char filename[])
{
	std::cout<<"save buffer to:"<<filename<<std::endl;
	std::ofstream fout(filename);
	unsigned char decodedS[9];
	for (unsigned int i=0;i<size;i+=8)
	{
		fout << std::dec << std::setw(6) << std::setfill(' ') << i<<"\t";
		rs400_decode_stringDebug(decodedS, &buf[i],8);
		for (unsigned int j=0;j<8;j++) fout << std::hex << std::setw(2) << std::setfill('0') << (int)buf[i+j]<<" ";
		fout<<"\t";
		for (unsigned int j=0;j<8;j++) fout<<std::dec<<decodedS[j]<<" ";
		fout<<"\n";
	}
	fout<<"\n";
	fout.close();
}

/* Save the data stored in the session structure into a HRM file */
void _saveHRM(const char filename[],rs400_session const &session)
{
	char time_str[12];

    FILE *fd = fopen(filename, "w");
    
    /* [Params] */
    fprintf(fd,
        "[Params]\r\n"
        "Version=107\r\n"
        "Monitor=36\r\n" /* RS400 */
    );
    fprintf(fd, "SMode=%d%d%d%d%d%d%d%d%d\r\n",
        session.has_pace_data ? 1 : 0, /* speed */
        0, /* cadence */
        0, /* altitude */
        0, /* power */
        0, /* power left right balance */
        0, /* power pedalling index */
        1, /* HR/CC data */
        session.si_units ? 0 : 1, /* SI / US units */
        0  /* air pressure */
    );
    fprintf(fd, "Date=%4d%02d%02d\r\n",
        session.year,
        session.month,
        session.day
    );
    fprintf(fd, "StartTime=%2d:%2d:%2d.0\r\n",
        session.start_hour,
        session.start_minute,
        session.start_second
    );
    timetostr(time_str, session.duration);
    fprintf(fd, "Length=%s\r\n", time_str);
    fprintf(fd, "Interval=%d\r\n",
        session.recording_interval
    );
    fprintf(fd, "Upper1=%d\r\n",
        0 /* TODO */
    );
    fprintf(fd, "Lower1=%d\r\n",
        0
    );
    fprintf(fd, "Upper2=%d\r\n",
        0
    );
    fprintf(fd, "Lower2=%d\r\n",
        0
    );
    fprintf(fd, "Upper3=%d\r\n",
        0
    );
    fprintf(fd, "Lower3=%d\r\n",
        0
    );
    timetostr(time_str, 0); /* TODO */
    fprintf(fd, "Timer1=%s\r\n", time_str);
    /* ...but spec says these are just mm:ss */
    timetostr(time_str, 0); 
    fprintf(fd, "Timer2=%s\r\n", time_str);
    timetostr(time_str, 0); /* TODO */
    fprintf(fd, "Timer3=%s\r\n", time_str);
    fprintf(fd, "ActiveLimit=%d\r\n",
        0 /* TODO */
    );
    fprintf(fd, "MaxHR=%d\r\n",
        /* Polar gets these from somewhere else? */
        session.user_hr_max
    );
    fprintf(fd, "RestHR=%d\r\n",
        session.user_hr_rest
    );
    fprintf(fd, "StartDelay=0\r\n");
    fprintf(fd, "VO2max=%d\r\n",
        session.user_vo2_max
    );
    fprintf(fd, "Weight=%d\r\n",
        session.user_weight //ej
    );

    /* [Note] */
    fprintf(fd, "\r\n[Note]\r\n");
		if (strlen(session.comment)>0 && session.comment[0]!='\r') fprintf(fd, "%s\r\n",session.comment);// Max 250 characters.
    
    /* [IntTimes] */
    fprintf(fd, "\r\n[IntTimes]\r\n");
    for(unsigned int i = 0; i < session.lap.size(); i++) {
        const rs400_lap *lap = &session.lap[i];
        timetostr(time_str, lap->lap_end_time);
        fprintf(fd, "%s\t%d\t%d\t%d\t%d\r\n", /* Row 1 */
            time_str, /* lap time */
            lap->hr_end,
            lap->hr_min,
            lap->hr_avg,
            lap->hr_max
        );
        fprintf(fd, "%d\t%d\t%d\t%d\t%d\t%d\r\n", /* Row 2 */
            0, /* flags */
            0, /* rec. time */
            0, /* rec. hr */
            (int) round(lap->pace_end / 25.6), /* momentary speed */
            0, /* momentary cadence */
            0 /* momentary altitude */
        );
        fprintf(fd, "%d\t%d\t%d\t%d\t%d\r\n", /* Row 3 */
            0, 0, 0, 0, 0 /* I think these will be empty */
        );
        fprintf(fd, "%d\t%d\t%d\t%d\t%d\t%d\r\n", /* Row 4 */
            lap->laptype, /* lap type */
            (int) round(lap->distance / 25.6), /* lap distance */
            0, /* power */
            0, /* temperature */
            0, /* phaselap */
            0
        );
        fprintf(fd, "%d\t%d\t%d\t%d\t%d\t%d\r\n", /* Row 5 - undocumented in spec? */
            0, 0, 0, 0, 0, 0
        );
    }

    /* [IntNotes] */
    fprintf(fd, "\r\n[IntNotes]\r\n");
		for (unsigned int i=0;i<session.lap.size();i++)
		{
			fprintf(fd, "%u\t%s\r\n",i,session.lap[i].note);
		}
    
    /* [ExtraData] */
    fprintf(fd, "\r\n[ExtraData]\r\n");
    /* Leave empty. */
    
    /* [Summary-123] */
    fprintf(fd, "\r\n[Summary-123]\r\n");
    for(unsigned int i = 0; i < 3; i++) {
        /* This should use the limiter zones but for now let's just use the totals. */
        //rs400_limiterzone *zone = &session.limiterzone[i];
        fprintf(fd, "%d\t%d\t%d\t%d\t%d\t%d\r\n",
            (int) round(session.duration), /* total time for selection */
            0, /* time with HR above max */
            0, /* time with HR between UL and max */
            (int) round(session.duration), /* time with HR between limits */
            0, /* time with HR between LL and rest */
            0  /* time with HR below rest */
        );
        fprintf(fd, "%d\t%d\t%d\t%d\r\n",
            session.user_hr_max, /* max HR */
            0, //zone->limit_high, /* UL */
            0, //zone->limit_low, /* LL */
            session.user_hr_rest  /* rest HR */
        );
    }
	if (session.selections.size()==0)
	{
		fprintf(fd, "%d\t%d\r\n", 0, (int) session.number_of_samples);
	}
	else
	{
		for (unsigned int i=0;i<session.selections.size();i++)
		{
			fprintf(fd, "%d\t%d\r\n", session.selections[i].low,session.selections[i].high);
		}
	}

	/* [Summary-TH] */
	/* For now only one summary is supported */
	fprintf(fd, "\r\n[Summary-TH]\r\n");
	fprintf(fd, "%d\t%d\t%d\t%d\t%d\t%d\r\n",	(int) round(session.duration),0,0,(int) round(session.duration),0,0);
	fprintf(fd, "%d\t%d\t%d\t%d\r\n",session.user_hr_max,0,0,session.user_hr_rest);
	fprintf(fd, "%d\t%d\t\r\n",0,session.number_of_samples);

	/* [HRZones] */
	fprintf(fd, "\r\n[HRZones]\r\n");
	for (unsigned int i=0;i<6;i++) fprintf(fd,"%d\r\n",(int) round(0.01*session.sportzone[5-i]* session.user_hr_max));
	for(unsigned int i = 0; i < 5; i++) fprintf(fd, "0\r\n");
  

	/* [SwapTimes] */
	fprintf(fd, "\r\n[SwapTimes]\r\n");
	/* Leave empty.  */
    
	/* [Trip] */
	fprintf(fd, "\r\n[Trip]\r\n");
	fprintf(fd, "%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n",
			(int) round(session.distance / 100.0),
			0, /* ascent */
			(int) round(session.duration),
			0, /* avg altitude */
			0, /* max altitude */
			session.pace_avg / 2,
			session.pace_max / 2,
			0 /* end odometer value */
	);
	
	/* [HRData] */
	fprintf(fd, "\r\n[HRData]\r\n");
	/* For some reason the first sample is duplicated */    
	fprintf(fd, "%d", session.sample[0].hr);
	if (session.has_pace_data) {
			/* Need to output in multiples of 1/10 km/h */
			fprintf(fd, "\t%d", (int) round(session.sample[0].speed / 25.6)); 
	}
	fprintf(fd, "\r\n");
//printf("number of samples2=%d\n",session.number_of_samples);
	for(unsigned int i = 0; i < session.number_of_samples; i++) {
			fprintf(fd, "%d", session.sample[i].hr);
			if (session.has_pace_data) {
					fprintf(fd, "\t%d", (int) round(session.sample[i].speed / 25.6));
			}
			fprintf(fd, "\r\n");
	}
	if (fd!=NULL) fclose(fd);
}





int CheckLine(FILE *fd,const char* what)
{
	char line[40];
	fgets (line , 40 , fd);
	//printf("checkline= %s",line);
	int comp = strncmp(line,what,strlen(what));
	if (comp ==0) return 0;
	else return -1;
}

int CheckLine1(FILE *fd,const char* what,const char *format, void* value)
{
	char line[40];
	fgets (line , 40 , fd);
	int comp1 = strncmp(line,what,strlen(what));
	int comp2 = sscanf (line+strlen(what),format,value);
	if (comp1==0 && comp2 ==1) return 0;
	else
	{
		printf("wrong file %s %d %d\n",what,comp1,comp2);
	}
	return -1;
}

int CheckLine2(FILE *fd,const char* what,const char *format, void* value,void* value2)
{
	char line[40];
	fgets (line , 40 , fd);
	int comp1 = strncmp(line,what,strlen(what));
	int comp2 = sscanf (line+strlen(what),format,value,value2);
	if (comp1==0 && comp2 ==2) return 0;
	//keep it silent
	/*
		else
		{
			printf("wrong file %s %d %d\n",what,comp1,comp2);
		}
		*/
	return -1;
}

int CheckLine1or2(FILE *fd,const char* what,const char *format, void* value,void* value2)
{
	char line[40];
	fgets (line , 40 , fd);
	int comp1 = strncmp(line,what,strlen(what));
	int comp2 = sscanf (line+strlen(what),format,value,value2);
	if (comp1==0 && (comp2 ==1 || comp2==2)) return 0;
	//keep it silent
	/*
		else
		{
			printf("wrong file %s %d %d\n",what,comp1,comp2);
		}
		*/
	return -1;
}


int CheckLine3(FILE *fd,const char* what,const char *format, void* value,void* value2,void* value3)
{
	char line[40];
	fgets (line , 40 , fd);
	int comp1 = strncmp(line,what,strlen(what));
	int comp2 = sscanf (line+strlen(what),format,value,value2,value3);
	if (comp1==0 && comp2 ==3) return 0;
	else
	{
		printf("wrong file %s %d %d\n",what,comp1,comp2);
	}
	return -1;
}

int CheckLine6(FILE *fd,const char* what,const char *format, void* value,void* value2,
			   void* value3,void* value4,void* value5,void* value6)
{
	char line[40];
	fgets (line , 40 , fd);
	int comp1 = strncmp(line,what,strlen(what));
	int comp2 = sscanf (line+strlen(what),format,value,value2,value3,value4,value5,value6);
	if (comp1==0 && comp2 ==6) return 0;
	else
	{
		printf("wrong file %s %d %d\n",what,comp1,comp2);
	}
	return -1;
}



#define find_or_die(str) \
if (CheckLine(fd,str)==-1) \
{if (fd!=NULL) {fclose(fd);fd=NULL;}\
return -1;}

#define find_or_die1(str,str2,where) \
if (CheckLine1(fd,str,str2,where)==-1) \
{if (fd!=NULL) {fclose(fd);fd=NULL;}\
return -1;}

#define find_or_die2(str,str2,where,where2) \
if (CheckLine2(fd,str,str2,where,where2)==-1) \
{if (fd!=NULL) {fclose(fd);fd=NULL;}\
return -1;}

#define find_or_die3(str,str2,where,where2,where3) \
if (CheckLine3(fd,str,str2,where,where2,where3)==-1) \
{if (fd!=NULL) {fclose(fd);fd=NULL;}\
return -1;}

#define find_or_die6(str,str2,where,where2,where3,where4,where5,where6) \
if (CheckLine6(fd,str,str2,where,where2,where3,where4,where5,where6)==-1) \
{if (fd!=NULL) {fclose(fd);fd=NULL;}\
return -1;}


#define check_existence(str) CheckLine(fd,str)

#define check_existence2(str,str2,where,where2) \
if (CheckLine2(fd,str,str2,where,where2)==-1) break;


#define skipline() 	fgets (tmp , 40 , fd)



/* load the file in the session structure */
int _readHRM(const char filename[],rs400_session &session)
{
	RS400_reset_session(&session);

	//printf("%s\n",filename);
	session.lap.clear();
	session.sample.clear();
	session.selections.clear();
    //unsigned int i;
    //char time_str[12];
	char tmp[40];
    FILE *fd = fopen(filename, "rt");

	unsigned int version,watch;
	unsigned int a,b,c,d,e,f,g,retval;

	find_or_die("[Params]");
	find_or_die1("Version=","%d",&version);
	find_or_die1("Monitor=","%d",&watch);
	find_or_die2("SMode=","%1d%*c%*c%*c%*c%*c%*c%c%*c",&session.has_pace_data,&session.si_units);
	find_or_die3("Date=","%4d%02d%02d",&session.year,&session.month,&session.day);
	find_or_die3("StartTime=","%2d%*c%2d%*c%2d",&session.start_hour,&session.start_minute,&session.start_second);

	find_or_die3("Length=","%2d%*c%2d%*c%2d",&a,&b,&c); session.duration=a*3600+b*60+c;
	find_or_die1("Interval=","%d",&session.recording_interval);

	find_or_die("Upper1=");
	find_or_die("Lower1=");
	find_or_die("Upper2=");
	find_or_die("Lower2=");
	find_or_die("Upper3");
	find_or_die("Lower3=");
	find_or_die("Timer1=");
	find_or_die("Timer2=");
	find_or_die("Timer3=");

	find_or_die("ActiveLimit=");
	find_or_die1("MaxHR=","%d",&session.user_hr_max);
	find_or_die1("RestHR=","%d",&session.user_hr_rest);
	find_or_die("StartDelay=");

	find_or_die1("VO2max=","%d",&session.user_vo2_max);
	find_or_die1("Weight=","%d",&session.user_weight); //equals zero in the file

	skipline();
	find_or_die("[Note]");
	fgets (session.comment , 250 , fd);
	//remove \r \n
	for (unsigned int i=0;i<strlen(session.comment);i++)
	{
		if (session.comment[i]=='\r' || session.comment[i]=='\n') session.comment[i]=' ';
	}
	
	
	//printf("comment :%s %d",session.comment,strlen(session.comment));
	if (strlen(session.comment)>2) skipline();
	
	find_or_die("[IntTimes]");

	session.number_of_laps=0;
	session.total_number_of_intervals=0;
	fgets (tmp , 40 , fd);
	
	rs400_lap lap0;
	while (strlen(tmp)>2)
	{
		retval = sscanf (tmp,"%2d%*c%2d%*c%2d%*c%*c %d %d %d %d",&a,&b,&c,&d,&e,&f,&g);
		if (retval!=7) {printf("bad file\n");return -1;}

		lap0.lap_end_time=a*3600+b*60+c;
		lap0.hr_end=d;
		lap0.hr_min=e;
		lap0.hr_avg=f;
		lap0.hr_max=g;

		skipline();
		skipline();

		fgets (tmp , 40 , fd);
		retval = sscanf (tmp,"%d %d %d %d %d %d",&a,&b,&c,&d,&e,&f);
		if (retval!=6) {printf("bad file\n");return -1;}
		lap0.laptype=a;
		if (a==0) {lap0.lap_no=session.number_of_laps+1;session.number_of_laps++;}
		else if (a==33554432) {lap0.lap_no=session.total_number_of_intervals+1;session.total_number_of_intervals++;}
		else lap0.lap_no=0;

		session.lap.push_back(lap0);

		//session.lap[session.number_of_laps-1]->distance=b*25.6;
		skipline(); //i don't read them. check file eof???
		skipline(); //check for new lap
	}
	//no more laps
	//printf("found %d laps\n",session.number_of_laps);
	//compute laps durations
	compute_laptimes(session);
	
	int status=-1;
	find_or_die("[IntNotes]");
	for (unsigned int i=0;i<session.number_of_laps+session.total_number_of_intervals;i++)
	{
		status=CheckLine1or2(fd,"","%d %s",&a,&session.lap[i].note);
		if (status==-1) break;
	}
	if (status!=-1) skipline(); //was ok, skip blank line

	find_or_die("[ExtraData]");
	skipline();

//lapnames do not always exist in the file
	fpos_t position;
	fgetpos (fd, &position);
	if (check_existence("[LapNames]")!=-1)
	{
		for (unsigned int i=0;i<session.number_of_laps+session.total_number_of_intervals;i++)
		{
			fgets (tmp , 40 , fd);
		}
		fgets (tmp , 40 , fd); //blanck line anyway
	}
	else fsetpos (fd, &position);

	find_or_die("[Summary-123]");
	skipline();
	skipline();
	skipline();
	skipline();
	skipline();
	skipline();
//read selections
	rs400_selection selectionTmp;

	for (unsigned int i=0;i<20;i++)
	{
		if (CheckLine2(fd,"","%d %d",&selectionTmp.low,&selectionTmp.high)==-1) break;
		session.selections.push_back(selectionTmp);
	}
	//printf("number of selections: %d\n",session.selections.size());

	find_or_die("[Summary-TH]");
	fgets (tmp , 40 , fd);
	fgets (tmp , 40 , fd);
	for (unsigned int i=0;i<20;i++)
	{
		fgets (tmp , 40 , fd);
		if (strlen(tmp)<=2) break;
	}	

	find_or_die("[HRZones]");
	find_or_die1("","%d",&session.sportzone[5]);
	find_or_die1("","%d",&session.sportzone[4]);
	find_or_die1("","%d",&session.sportzone[3]);
	find_or_die1("","%d",&session.sportzone[2]);
	find_or_die1("","%d",&session.sportzone[1]);
	find_or_die1("","%d",&session.sportzone[0]);
	skipline();
	skipline();
	skipline();
	skipline();
	skipline();
	session.sportzone[5]*=(100.0/session.user_hr_max);
	session.sportzone[4]*=(100.0/session.user_hr_max);
	session.sportzone[3]*=(100.0/session.user_hr_max);
	session.sportzone[2]*=(100.0/session.user_hr_max);
	session.sportzone[1]*=(100.0/session.user_hr_max);
	session.sportzone[0]*=(100.0/session.user_hr_max);

	skipline();
	find_or_die("[SwapTimes]");
	skipline();

//trip do not always exist in the file
	if (!session.has_pace_data)
	{
		session.distance=0;
		session.pace_avg=0;
		session.pace_max=0;
	}

	fgetpos (fd, &position);
	if (check_existence("[Trip]")!=-1)
	{
		find_or_die1("","%d",&session.distance);
		find_or_die("");
		find_or_die1("","%lf",&session.duration);
		find_or_die("");
		find_or_die("");
		find_or_die1("","%d",&session.pace_avg);
		find_or_die1("","%d",&session.pace_max);
		find_or_die("");
		skipline();
		session.distance*=100;
		session.pace_avg*=2;
		session.pace_max*=2;
	}
	else fsetpos (fd, &position);


	find_or_die("[HRData]");
	session.number_of_samples = session.duration / session.recording_interval+1;
	//printf("number of samples =%d\n",session.number_of_samples);

	rs400_sample sample0;
	//first sample duplicated
	if (!session.has_pace_data) fscanf(fd,"%d",&sample0.hr);
	else fscanf(fd,"%d %d",&sample0.hr,&sample0.speed);
	session.sample.push_back(sample0);
	
	for (unsigned int i=0;i<session.number_of_samples; i++)
	{
       if (!session.has_pace_data) fscanf(fd,"%d",&sample0.hr);
		else fscanf(fd,"%d %d",&sample0.hr,&sample0.speed);
		session.sample.push_back(sample0);
	}

if (fd!=NULL) fclose(fd);
return 0;
}

int _readPDDoverview(const char filename[])
{
	struct stat filebuf;
	int         status;

	status = stat(filename, &filebuf);
	if (status!=0) return -1;

	unsigned int a,b,c,d,e,f;
  FILE *fd = fopen(filename, "rt");
	find_or_die("[DayInfo]");
	find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&a,&b,&c,&d,&e,&f);
	find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&a,&b,&c,&d,&e,&f);
	if (fd!=NULL) fclose(fd);
	return b;
}


int _readPDD(const char filename[], rs400_pdd_content &info)
{
	info.exerciseinfo.clear();
	struct stat filebuf;
	int         status;

	status = stat(filename, &filebuf);
	if (status!=0) return -1;

	unsigned int a,b,c,d,e,f;
	//printf("%s\n",filename);

	char tmp[40];
	char strtmp[512];
    FILE *fd = fopen(filename, "rt");

	find_or_die("[DayInfo]");
	find_or_die6("","%d %d %d %d %d %d",
							 &info.dayinfo.fileVersionDAY,&info.dayinfo.nbrInfoRowsDAY,&info.dayinfo.nbrNumRowsDAY,
							 &info.dayinfo.nbrNumColumnsDAY,&info.dayinfo.nbrTextRowsDAY,&info.dayinfo.maxCharPerTextRowDAY);

	find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",
							 &info.dayinfo.date,&info.dayinfo.nbrExercises,&info.dayinfo.restingHR,
							 &info.dayinfo.orthoHR,&info.dayinfo.weight,&info.dayinfo.sleepingHours);

	find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&info.dayinfo.sleepingPattern,&b,&c,&d,&e,&f);
	find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&info.dayinfo.dayInfoData,&b,&c,&d,&e,&f);
	find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&a,&b,&info.dayinfo.polarOwnIndex,
							 &info.dayinfo.weather,&info.dayinfo.temperature,&f);
	
	//for now, just skip TODO
	for (unsigned int i=0;i<info.dayinfo.nbrNumRowsDAY-4;i++)
	{
		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&a,&b,&c,&d,&e,&f);
	}

	for (unsigned int i=0;i<info.dayinfo.nbrTextRowsDAY;i++) skipline();

	rs400_pdd_exercise_info exInfo;
	for (unsigned int nb=0;nb<info.dayinfo.nbrExercises;nb++)
	{
		skipline();
		find_or_die("[ExerciseInfo");
		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",
								 &exInfo.fileVersionDAY,&exInfo.nbrInfoRows,&exInfo.nbrNumRows,
								 &exInfo.nbrNumColumns,&exInfo.nbrTextRows,&exInfo.maxCharPerTextRow);

		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&a,&b,&c,&d,
								 &exInfo.startTime,
								 &exInfo.totalTime);

		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",
								 &exInfo.sport,&exInfo.distanceOLD,&exInfo.feeling,
								 &exInfo.recovery,&a,&exInfo.energy);

		//skip two, TODO
		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&a,&b,&c,&d,&e,&f);
		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&a,&b,&c,&d,&e,&f);

		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",\
					&exInfo.zone0Time,&exInfo.zone1Time,&exInfo.zone2Time,\
					&exInfo.zone3Time,&exInfo.zone4Time,&exInfo.zone5Time);

		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",\
					&exInfo.zone6Time,&exInfo.zone7Time,&exInfo.zone8Time,\
					&exInfo.zone9Time,&a,&b);

		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",\
					&exInfo.zone0Exertion,&exInfo.zone1Exertion,&exInfo.zone2Exertion,\
					&exInfo.zone3Exertion,&exInfo.zone4Exertion,&exInfo.zone5Exertion);

		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",\
					&exInfo.zone6Exertion,&exInfo.zone7Exertion,&exInfo.zone8Exertion,\
					&exInfo.zone9Exertion,&exInfo.recordingRate,&a);

		find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",\
					&exInfo.HRaverage,&exInfo.HRmax,&exInfo.speedAverage,\
					&exInfo.speedMax,&exInfo.cadenceAverage,&exInfo.cadenceMax);
		//skip things TODO
		for (unsigned i=0;i<exInfo.nbrNumRows-9;i++)
			find_or_die6("","%d\t%d\t%d\t%d\t%d\t%d",&a,&b,&c,&d,&e,&f);

		//remove \r\n
		fgets (strtmp,    512 , fd); strncpy(exInfo.exoName,strtmp,strlen(strtmp)-2);
		exInfo.exoName[strlen(strtmp)-2]='\0';
		fgets (strtmp,    512 , fd); strncpy(exInfo.exoNote,strtmp,strlen(strtmp)-2);
		exInfo.exoNote[strlen(strtmp)-2]='\0';
		fgets (strtmp,    512 , fd); strncpy(exInfo.exoHRMfile,strtmp,strlen(strtmp)-2);
		exInfo.exoHRMfile[strlen(strtmp)-2]='\0';

		
		for (unsigned i=0;i<exInfo.nbrTextRows-3;i++)
		{
			fgets (strtmp,    512 , fd); strncpy(exInfo.row3,strtmp,strlen(strtmp)-2);
			exInfo.row3[strlen(strtmp)-2]='\0';
		}
		info.exerciseinfo.push_back(exInfo);
	}
	if (fd!=NULL) fclose(fd);
	return 0;
}

void _savePDD(const char filename[], rs400_pdd_content const &info)
{
	FILE *fd = fopen(filename, "wt");
  fprintf(fd, "[DayInfo]\r\n");
	fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
					info.dayinfo.fileVersionDAY,info.dayinfo.nbrInfoRowsDAY,info.dayinfo.nbrNumRowsDAY,
					info.dayinfo.nbrNumColumnsDAY,info.dayinfo.nbrTextRowsDAY,info.dayinfo.maxCharPerTextRowDAY);

	fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
					info.dayinfo.date,info.dayinfo.nbrExercises,info.dayinfo.restingHR,
					info.dayinfo.orthoHR,info.dayinfo.weight,info.dayinfo.sleepingHours);

	fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",info.dayinfo.sleepingPattern,0,0,0,0,0);
	fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",info.dayinfo.dayInfoData,0,0,0,0,0);
	fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",0,0,info.dayinfo.polarOwnIndex,info.dayinfo.weather,info.dayinfo.temperature,0);

	//for now, just skip TODO
	for (unsigned int i=0;i<info.dayinfo.nbrNumRowsDAY-4;i++)
	{
		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",0,0,0,0,0,0);
	}

	for (unsigned int i=0;i<info.dayinfo.nbrTextRowsDAY;i++) fprintf(fd, " \r\n");

	for (unsigned int nb=0;nb<info.dayinfo.nbrExercises;nb++)
	{
		fprintf(fd, " \r\n");
		fprintf(fd, "[ExerciseInfo%d]\r\n",nb+1);

		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
						info.exerciseinfo[nb].fileVersionDAY,info.exerciseinfo[nb].nbrInfoRows,info.exerciseinfo[nb].nbrNumRows,
						info.exerciseinfo[nb].nbrNumColumns,info.exerciseinfo[nb].nbrTextRows,info.exerciseinfo[nb].maxCharPerTextRow);

		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",0,0,0,0,
						info.exerciseinfo[nb].startTime,
						info.exerciseinfo[nb].totalTime);

		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
						info.exerciseinfo[nb].sport,info.exerciseinfo[nb].distanceOLD,info.exerciseinfo[nb].feeling,
						info.exerciseinfo[nb].recovery,0,info.exerciseinfo[nb].energy);

		//skip two, TODO
		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",0,0,0,0,0,0);
		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",0,0,0,0,0,0);

		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
						info.exerciseinfo[nb].zone0Time,info.exerciseinfo[nb].zone1Time,info.exerciseinfo[nb].zone2Time,
						info.exerciseinfo[nb].zone3Time,info.exerciseinfo[nb].zone4Time,info.exerciseinfo[nb].zone5Time);

		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
						info.exerciseinfo[nb].zone6Time,info.exerciseinfo[nb].zone7Time,info.exerciseinfo[nb].zone8Time,
						info.exerciseinfo[nb].zone9Time,0,0);

		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
						info.exerciseinfo[nb].zone0Exertion,info.exerciseinfo[nb].zone1Exertion,info.exerciseinfo[nb].zone2Exertion,
						info.exerciseinfo[nb].zone3Exertion,info.exerciseinfo[nb].zone4Exertion,info.exerciseinfo[nb].zone5Exertion);

		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
						info.exerciseinfo[nb].zone6Exertion,info.exerciseinfo[nb].zone7Exertion,info.exerciseinfo[nb].zone8Exertion,
						info.exerciseinfo[nb].zone9Exertion,info.exerciseinfo[nb].recordingRate,0);

		fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",
						info.exerciseinfo[nb].HRaverage,info.exerciseinfo[nb].HRmax,info.exerciseinfo[nb].speedAverage,
						info.exerciseinfo[nb].speedMax,info.exerciseinfo[nb].cadenceAverage,info.exerciseinfo[nb].cadenceMax);
		
		//skip things TODO
		for (unsigned i=0;i<info.exerciseinfo[nb].nbrNumRows-9;i++)
			fprintf(fd,"%d\t%d\t%d\t%d\t%d\t%d\r\n",0,0,0,0,0,0);

		fprintf(fd,"%s\r\n",info.exerciseinfo[nb].exoName);
		fprintf(fd,"%s\r\n",info.exerciseinfo[nb].exoNote);
		fprintf(fd,"%s\r\n",info.exerciseinfo[nb].exoHRMfile);

		for (unsigned i=0;i<info.exerciseinfo[nb].nbrTextRows-3;i++) 	fprintf(fd," \r\n");
	}
	if (fd!=NULL) fclose(fd);
}
